/*
    @File:      Access_Motion.c    
    @Author:    Tomás González Sánchez
    @Date:      25/10/06
    @e-address: gonzalezt@gmail.com
*/

#include "Access_Motion.h"

  int num_cameras;

  typedef struct {
    char name_cameras[LENG_NAME];
	char alias[LENG_NAME];
	int pid;
	int port;
    int iden; // numeric identifier
    float frame_rate;
    int rows;
    int cols;
    int color; // TRUE ==> Color, FALSE ==> BN
    char directory[LENG_DIR];
    int gap_time;       //Default 60
    int fr_pre_capture; //numero de frames de pre_captura 0..100: Recomended 5
    int threshold;  
    char start_event[LENG_NAME];
    char end_event[LENG_NAME];
    int max_duration; //Max Video Duration
	int active;
	int start;
  } Tcamera; //Type Camera

 Tcamera system_cams[NUM_CAMERAS];

 int AM_Set_Modificar_port(char *name, int port)
 {
    int j = 0;
    int trobat = FALSE;

    while((!trobat) && (j<num_cameras))
    {
        if (port == system_cams[j].port)
          {  trobat=TRUE;
             system_cams[j].port=port;
             return(system_cams[j].port);                                
          }
        j++;
    }

    /*Rows not change*/
    return(-1);
 }

 int AM_Set_Modificar_PID(char *name, int pid)
 {
    int j = 0;
    int trobat = FALSE;

    while((!trobat) && (j<num_cameras))
    {
        if (strcmp(name,system_cams[j].name_cameras) ==0)
          {  trobat=TRUE;
             system_cams[j].pid=pid;
             return(system_cams[j].pid);                                
          }
        j++;
    }

    /*PID not change*/
    return(-1);
 }

 int AM_Set_Modificar_Alies(char *name, char *alies)
 {
    int j = 0;
    int trobat = FALSE;

    while((!trobat) && (j<num_cameras))
    {
        if (strcmp(name,system_cams[j].name_cameras) ==0)
          {  trobat=TRUE;
             strcpy(system_cams[j].alias,alies);
             return(TRUE);                                
          }
        j++;
    }

    /*Alias not change*/
    return(-1);
 }
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
 /*
  Insert a new Camera referenced by name ex: /dev/video0
  The method returns the identifier number.
  If limite of cameras that are soported by the library are arrible
  -1 will returned.
 */
 int AM_Set_NewCam(char *name, float fr, int rows, int cols, int color_BN, char *dir, int gap,
                   int fr_pre_capture, int threshold, char *start_event_script,
				   char *end_event_script, int pid, int port, char *alias,int duration)
 {
    if (num_cameras == NUM_CAMERAS)  return(-1);
    else
    {
        strcpy(system_cams[num_cameras].name_cameras, name);
        system_cams[num_cameras].iden = num_cameras;
        system_cams[num_cameras].frame_rate = fr;
        system_cams[num_cameras].rows = rows;
        system_cams[num_cameras].cols = cols;
        system_cams[num_cameras].color = color_BN;
        strcpy(system_cams[num_cameras].directory,dir);
        system_cams[num_cameras].gap_time = gap;
        system_cams[num_cameras].fr_pre_capture = fr_pre_capture;
        system_cams[num_cameras].threshold = threshold;
        strcpy(system_cams[num_cameras].start_event, start_event_script);
        strcpy(system_cams[num_cameras].end_event, end_event_script);
		strcpy(system_cams[num_cameras].alias, alias);
		system_cams[num_cameras].port = port;
		system_cams[num_cameras].pid = pid;
		system_cams[num_cameras].max_duration=duration;
		// default parametric values
		system_cams[num_cameras].active =1; // The motion method is ON
		system_cams[num_cameras].start  =0; // The continue video recording is OFF
        num_cameras++;
        return(num_cameras-1);
    }
 }
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/*

*/
 int AM_Set_Rows(char *name, int rows)
 {
    int j = 0;
    int trobat = FALSE;

    while((!trobat) && (j<num_cameras))
    {
        if (strcmp(name,system_cams[j].name_cameras) ==0)
          {  trobat=TRUE;
             system_cams[j].rows=rows;
             return(system_cams[j].rows);                                
          }
        j++;
    }

    /*Rows not change*/
    return(-1);  
 }

 int AM_Set_RowsPos(int pos, int rows)
 {
	if (pos < num_cameras)
	{ 
	system_cams[pos].rows=rows;
    return(system_cams[pos].rows);
	}
	else return(-1);
 }


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
 int AM_Set_Cols(char *name, int cols)
 {
    int j = 0;
    int trobat = FALSE;

    while((!trobat) && (j<num_cameras))
    {
        if (strcmp(name,system_cams[j].name_cameras) ==0)
          {  trobat=TRUE;
             system_cams[j].cols=cols;
             return(system_cams[j].cols);                                
          }
        j++;
    }

    /*Cols not change*/
    return(-1);  
 }
 
 int AM_Set_ColsPos(int pos, int cols)
 {
	if (pos < num_cameras)
	{ 
	system_cams[pos].cols=cols;
    return(system_cams[pos].cols);
	}
	else return(-1);
 }
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

 int AM_Set_Color_BN(char *name, int valor) //valor :: TRUE o FALSE
 {
    int j = 0;
    int trobat = FALSE;

    while((!trobat) && (j<num_cameras))
    {
        if (strcmp(name,system_cams[j].name_cameras) ==0)
          {  trobat=TRUE;
             system_cams[j].color=valor;
             return(system_cams[j].color);                                
          }
        j++;
    }

    /*Color_BN not change*/
    return(-1);  
 }

 int AM_Set_Color_BNPos(int pos, int valor)//valor :: TRUE o FALSE
 {
	if (pos < num_cameras)
	{ 
	system_cams[pos].color=valor;
    return(system_cams[pos].color);
	}
	else return(-1);
 }
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

 int AM_Set_Directory(char *name, char *dir)
  {
    int j = 0;
    int trobat = FALSE;

    while((!trobat) && (j<num_cameras))
    {
        if (strcmp(name,system_cams[j].name_cameras) ==0)
          {  trobat=TRUE;
             strcpy(system_cams[j].directory,dir);
             return(TRUE);                                
          }
        j++;
    }

    /*Directory not change*/
    return(-1);  
 }
 
 int AM_Set_DirectoryPos(int pos, char *dir)
 {
	if (pos < num_cameras)
	{ 
	strcpy(system_cams[pos].directory,dir);
    return(TRUE);
	}
	else return(-1);
 }

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

 int AM_Set_GapMotion(char *name,int gap)
 {
    int j = 0;
    int trobat = FALSE;

    while((!trobat) && (j<num_cameras))
    {
        if (strcmp(name,system_cams[j].name_cameras) ==0)
          {  trobat=TRUE;
             system_cams[j].gap_time=gap;
             return(system_cams[j].gap_time);                                
          }
        j++;
    }

    /*Rows not change*/
    return(-1);  
 }
 int AM_Set_GapMotionPos(int pos, int gap)
 {
	if (pos < num_cameras)
	{ 
	system_cams[pos].gap_time=gap;
    return(system_cams[pos].gap_time);
	}
	else return(-1);
 }

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

 int AM_Set_Frame_precapture(char *name, int num_frames)
 {
    int j = 0;
    int trobat = FALSE;

    while((!trobat) && (j<num_cameras))
    {
        if (strcmp(name,system_cams[j].name_cameras) ==0)
          {  trobat=TRUE;
             system_cams[j].fr_pre_capture=num_frames;
             return(system_cams[j].fr_pre_capture);                                
          }
        j++;
    }

    /*fr_pre_capture not change*/
    return(-1);  
 }


 int AM_Set_Frame_precapturePos(int pos, int num_frames)
 {
	if (pos < num_cameras)
	{ 
	system_cams[pos].fr_pre_capture=num_frames;
    return(system_cams[pos].fr_pre_capture);
	}
	else return(-1);
 }

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

 int AM_Set_Threshold(char *name, int threshold) //sensibility
 {
    int j = 0;
    int trobat = FALSE;

    while((!trobat) && (j<num_cameras))
    {
        if (strcmp(name,system_cams[j].name_cameras) ==0)
          {  trobat=TRUE;
             system_cams[j].threshold=threshold;
             return(system_cams[j].threshold);                                
          }
        j++;
    }

    /*threshold not change*/
    return(-1);  
 }


 int AM_Set_ThresholdPos(int pos, int threshold)
 {
	if (pos < num_cameras)
	{ 
	system_cams[pos].threshold=threshold;
    return(system_cams[pos].threshold);
	}
	else return(-1);
 }

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

 int AM_Set_start_event_script(char *name, char *start_event_script)
 {
    int j = 0;
    int trobat = FALSE;

    while((!trobat) && (j<num_cameras))
    {
        if (strcmp(name,system_cams[j].name_cameras) ==0)
          {  trobat=TRUE;
             strcpy(system_cams[j].start_event,start_event_script);
             return(TRUE);                                
          }
        j++;
    }

    /*Start_event_script not change*/
    return(-1);  
 }

 int AM_Set_start_event_scriptPos(int pos, char *start_event_script)
 {
	if (pos < num_cameras)
	{ 
         strcpy(system_cams[pos].start_event,start_event_script);
         return(TRUE);                                
	}
	else return(-1);
 }

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

 int AM_Set_end_event_script(char *name, char *end_event_script)
 {
    int j = 0;
    int trobat = FALSE;

    while((!trobat) && (j<num_cameras))
    {
        if (strcmp(name,system_cams[j].name_cameras) ==0)
          {  trobat=TRUE;
             strcpy(system_cams[j].end_event,end_event_script);
             return(TRUE);                                
          }
        j++;
    }

    /*Start_event_script not change*/
    return(-1);  
 }
 int AM_Set_end_event_scriptPos(int pos, char *end_event_script)
 {
	if (pos < num_cameras)
	{ 
         strcpy(system_cams[pos].end_event,end_event_script);
         return(TRUE);                                
	}
	else return(-1);
 }


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
 
 /*
  The method return the number of cameras that are inserted yet.
 */
 int AM_Get_NumCams()
 {
    return(num_cameras);
 }

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 
 /*
  This methods are used to change and consult the Frame Rate of a determined Camera
  We can identify the camera by name or by the identifier of the camera in the library
  Changed Frame Rate is returned, if error occurs it will return -1
 */

 int AM_Set_FrameRate(char *name, float fr)
 {
    int j = 0;
    int trobat = FALSE;

    while((!trobat) && (j<num_cameras))
    {
        if (strcmp(name,system_cams[j].name_cameras) ==0)
          {  trobat=TRUE;
             system_cams[j].frame_rate=fr;
             return(system_cams[j].frame_rate);                                
          }
        j++;
    }

    /*Frame Rate change*/
    return(-1);
 }

 int AM_Set_FrameRatePos(int pos, float fr)
 {
    if ( pos >= num_cameras)  return (-1);
    system_cams[pos].frame_rate = fr;
    return(system_cams[pos].frame_rate);
 }

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

 float AM_Get_FrameRate(char *name)
 {
    int j = 0;
    int trobat = FALSE;

    while((!trobat) && (j<num_cameras))
    {
        if (strcmp(name,system_cams[j].name_cameras) == 0)
          {  trobat=TRUE;
             return(system_cams[j].frame_rate);                                
          }
        j++;
    }

    return(-1);

 }
    
 float AM_Get_FrameRatePos(int pos)
 {
    if ( pos >= num_cameras)  return (-1);
    return(system_cams[pos].frame_rate);
 }

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/*
 Set Maximum video duration in secords
*/
 int AM_Set_Max_Video_Duration(char *name, int duration)
{
    int j = 0;
    int trobat = FALSE;

    while((!trobat) && (j<num_cameras))
    {
        if (strcmp(name,system_cams[j].name_cameras) ==0)
          {  trobat=TRUE;
             system_cams[j].max_duration=duration;
             return(system_cams[j].max_duration);                                
          }
        j++;
    }

    /*Video duration change*/
    return(-1);
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

/*
  Creates the motion configuration file at path_name  
  Returned -1 if open error file access is success
 */

 int AM_Create_MotionFile(char *path_name, char *name)
 {
    int j = 0;
    int trobat = FALSE;

    while((!trobat) && (j<num_cameras))
    {
        if (strcmp(name,system_cams[j].name_cameras) == 0)
          {  trobat=TRUE;
             AM_Create_MotionFilePos(path_name, j);                                
          }
        j++;
    }

    return(-1);
    
 }

void AM_Create_Motion_Out(FILE *fmotion, int pos, char *path_name)
{
    char aux_s[20];
	int tmp;
	float ff;
    fprintf(fmotion,"# Fitxer de configuracio del demoni Motion: %s\n",path_name);
    fprintf(fmotion,"# Minimal motion example config file provided by the");
    fprintf(fmotion,"\n# Debian motion package - for basic webcam operation.");
    fprintf(fmotion,"\n#");
    fprintf(fmotion,"\n# You most certainly want to investigate");
    fprintf(fmotion,"\n# /usr/share/doc/motion/examples/motion-dist.conf.gz");
    fprintf(fmotion,"\n# for further configuration options. Also, refer to the");
    fprintf(fmotion,"\n# motion man page and /usr/share/doc/motion/motion_guide.html");
    fprintf(fmotion,"\n# for detailed information on configuration options.\n");
	
	fprintf(fmotion,"\n#/tmp/motion_%s.%i\n",system_cams[pos].alias,system_cams[pos].pid);
    fprintf(fmotion,"\ndaemon on\n");
    fprintf(fmotion,"quiet on\n");

    fprintf(fmotion,"\n# You may very well need to change this (check with 'dmesg'\n");
    fprintf(fmotion,"# after plugging in your webcam)\n");
//    fprintf(fmotion,"videodevice /dev/video0\n");
    fprintf(fmotion,"videodevice %s\n", system_cams[pos].name_cameras); //dev/video0

    fprintf(fmotion,"\n# Image size in pixels (valid range is camera dependent)\n");
//    fprintf(fmotion,"width 320\n");
//    fprintf(fmotion,"height 240\n");
    sprintf(aux_s,"%i",system_cams[pos].rows);
    fprintf(fmotion,"width %s\n",aux_s);
    
    sprintf(aux_s,"%i",system_cams[pos].cols);
    fprintf(fmotion,"height %s\n",aux_s);

    

    fprintf(fmotion,"#Motion Detection parameters\n");
    fprintf(fmotion,"#despeckle eEdD\n");

//    fprintf(fmotion,"\nframerate 25\n");
	
	if (system_cams[pos].frame_rate >=2)
		{
		sprintf(aux_s,"%i",(int)system_cams[pos].frame_rate);
    	fprintf(fmotion,"\nframerate %s\n",aux_s);
		}
	else	//time between cameras
		{
		ff = 1./system_cams[pos].frame_rate;
		tmp = ff;
		//printf("!!! %d\n",tmp);
		//printf("!!! %f\n",ff);
		sprintf(aux_s,"%d",tmp);
		fprintf(fmotion,"\nminimum_frame_time %s\n",aux_s);
		}
    //fprintf(fmotion,"\nframerate %s\n",aux_s);
    fprintf(fmotion,"quality 85\n");
    fprintf(fmotion,"auto_brightness off\n");

    fprintf(fmotion,"\n# Initial brightness, contrast, hue (NTSC), and saturation\n");
    fprintf(fmotion,"# 0 = disabled (valid range 0-255)\n");
    fprintf(fmotion,"brightness 0\n");
    fprintf(fmotion,"contrast 0\n");
    fprintf(fmotion,"saturation 0\n");
    fprintf(fmotion,"hue 0\n");

    fprintf(fmotion,"\n#Select the norm of the video device.\n");
    fprintf(fmotion,"#Values: 0 (PAL), 1 (NTSC), 2 (SECAM), 3 (PAL NC  no colour). Default: 0 (PAL)\n");
    if (system_cams[pos].color == TRUE) fprintf(fmotion,"norm 0\n");
    else fprintf(fmotion,"norm 3\n");

    fprintf(fmotion,"\n# Encode movies in real-time (install ffmpeg before enabling)\n");
    fprintf(fmotion,"ffmpeg_cap_new on\n");

    fprintf(fmotion,"\n# Codec to be used by ffmpeg for the video compression.\n");
    fprintf(fmotion,"# Supported formats: mpeg4, msmpeg4.\n");
    fprintf(fmotion,"ffmpeg_video_codec msmpeg4\n");
	fprintf(fmotion,"output_normal off\n");

    fprintf(fmotion,"\n# Target base directory for pictures and films\n");
    fprintf(fmotion,"# You should probably change this (create dir beforehand)\n");
    fprintf(fmotion,"target_dir %s\n",system_cams[pos].directory);

    fprintf(fmotion,"\n# Define a port number (e.g. 8000) to enable the mini-http server\n");
    fprintf(fmotion,"# 0 = disabled\n");
    fprintf(fmotion,"webcam_port %i\n",system_cams[pos].port);

    fprintf(fmotion,"\n# Set to 'off' to allow anybody (not just localhost) to view the\n");
    fprintf(fmotion,"# webcam via the mini-http server (http://hostname:port)\n");
    fprintf(fmotion,"webcam_localhost on\n");


    fprintf(fmotion,"\n# TCP/IP port for the http server to listen on (default: 0 = disabled)\n");
    fprintf(fmotion,"control_port 0\n");

    fprintf(fmotion,"\n# Restrict control connections to localhost only (default: on)\n");
    fprintf(fmotion,"control_localhost on\n");

    fprintf(fmotion,"\n# Output for http server, select off to choose raw text plain (default: on)\n");
    fprintf(fmotion,"control_html_output on\n");

    fprintf(fmotion,"\n# Authentication for the http based control. Syntax username:password\n");
    fprintf(fmotion,"# Default: not defined (Disabled)\n");
    fprintf(fmotion,"\n# Authentication for the http based control. Syntax username:password\n");
    fprintf(fmotion,"# Default: not defined (Disabled)\n");
    fprintf(fmotion,"; control_authentication username:password\n");

    fprintf(fmotion,"\n#Time Eleapsed before an even occours\n");
    sprintf(aux_s,"%i",system_cams[pos].gap_time);
    fprintf(fmotion,"gap %s\n",aux_s);

    fprintf(fmotion,"\n#Specifies the number of previous frames to be outputted at motion detection\n");
    sprintf(aux_s,"%i",system_cams[pos].fr_pre_capture);
    fprintf(fmotion,"pre_capture %s\n",aux_s);
	
	fprintf(fmotion,"\n#Specifies the maximum video duration on a motion detection\n");
    sprintf(aux_s,"%i",system_cams[pos].max_duration);
    fprintf(fmotion,"max_mpeg_time %s\n",aux_s);

    fprintf(fmotion,"\n#The threshold is the number of changed pixels counted after noise filtering\n");
    fprintf(fmotion,"#default 1500\n");
	if (system_cams[pos].start == 1)  sprintf(aux_s,"%i",0);
    else
		{
		if (system_cams[pos].active == 0) sprintf(aux_s,"%i",(system_cams[pos].rows*system_cams[pos].cols)+1);
		else sprintf(aux_s,"%i",system_cams[pos].threshold);
		}
	fprintf(fmotion,"threshold %s\n",aux_s);
    fprintf(fmotion,"threshold_tune off\n");

    sprintf(aux_s,"%s",system_cams[pos].start_event);
    fprintf(fmotion,"\non_event_start %s\n",aux_s);

    sprintf(aux_s,"%s",system_cams[pos].end_event);
    fprintf(fmotion,"on_motion_detected %s\n",aux_s);
}

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
 int AM_Create_MotionFilePos(char *path_name, int pos)
 {
    FILE *fmotion;
    char aux_s[20];
    char dummy[20];

    fmotion = fopen(path_name,"w");
    if (!fmotion)
    {
      printf("no puc obrir el fitxer %s\n", path_name);
      return(-1);
    }  
    AM_Create_Motion_Out(fmotion,pos,path_name);
    fclose(fmotion);
    return 0;
 
 }

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/*
 Set the sensibility of the motion detection method to 100%
 (0 pixels change) to allow the Continue Video Recording 
*/
 int AM_Inici_Gravacio_continua(char *name)
 {
    int j = 0;
    int trobat = FALSE;

    while((!trobat) && (j<num_cameras))
    {
        if (strcmp(name,system_cams[j].name_cameras) ==0)
          {  trobat=TRUE;
			 system_cams[j].start = 1;
             return(TRUE);                               
          }
        j++;
    }

    /*No changed start field*/
    return(-1);
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/*
 Set the assigned values of a camera to allow Motion Detection
*/
 int AM_Fi_Gravacio_continua(char *name)
 {
    int j = 0;
    int trobat = FALSE;

    while((!trobat) && (j<num_cameras))
    {
        if (strcmp(name,system_cams[j].name_cameras) ==0)
          {  trobat=TRUE;
			 system_cams[j].start = 0;
             return(TRUE);                               
          }
        j++;
    }

    /*No changed start field*/
    return(-1);
 }
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/*
 Set the assigned values of a camera to allow Motion Detection
*/
 int AM_Activar_Deteccio(char *name)
 {
    int j = 0;
    int trobat = FALSE;

    while((!trobat) && (j<num_cameras))
    {
        if (strcmp(name,system_cams[j].name_cameras) ==0)
          {  trobat=TRUE;
			 system_cams[j].active = 1;
             return(TRUE);                               
          }
        j++;
    }

    /*No changed active field*/
    return(-1);
 }
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/*
 Set the sensibility of the motion detection method to 0%
 (All pixels must change) to allow the Continue Video Recording 
*/
 int AM_Desactivar_Deteccio(char *name)
 {
    int j = 0;
    int trobat = FALSE;

    while((!trobat) && (j<num_cameras))
    {
        if (strcmp(name,system_cams[j].name_cameras) ==0)
          {  trobat=TRUE;
			 system_cams[j].active = 0;
             return(TRUE);                               
          }
        j++;
    }

    /*No changed active field*/
    return(-1);
 }




